package com.pic.mgt.telnetd;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.apache.commons.lang.StringUtils;

import com.pic.mgt.log.IgxLog;
import com.pic.mgt.utils.IgxUtils;

public class ShellCommandHandler {
	private final String NO_SUCH_COMMAND_MESSAGE = "No such command can be performed. Try 'help' to get command description.";
	private final String COMMAND_PARAM_INCORRECT_MESSAGE = "Invalid parameters. Try '-help' to get parameter description.";
	
	private Map<String, CommandPerformer> commandPerformerMap;
	
	public ShellCommandHandler() {
		commandPerformerMap = new HashMap<String, CommandPerformer>();
	}
	
	
	/**
	 * @param commandLineStr 指令(含參數)列字弗
	 * @return 指令執行結果訊息
	 */
	public String handleCommand(String commandLineStr) {
		// 取得指令名稱
		String commandName = StringUtils.substringBefore(commandLineStr, " ").trim();
		
		// 取得指令參數
		String[] commandParamsLine = null;
		String commandParamsLineStr = StringUtils.substringAfter(commandLineStr, " ").trim();
		if (commandParamsLineStr.length() > 0) {
			commandParamsLine = IgxUtils.parseShellCommandLineStrToArray(commandParamsLineStr);
		}
		else {
			commandParamsLine = new String[]{};
		}
		
		if (null == commandName) {
			// 找不到指令
			return NO_SUCH_COMMAND_MESSAGE;
		}
		
		CommandPerformer commandPerformer = this.commandPerformerMap.get(commandName);
		
		if (null == commandPerformer) {
			// 找不到指令
			return NO_SUCH_COMMAND_MESSAGE;
		}
		
		// 分析指令的參數
		CommandLine commandLine;
		try {
			CommandLineParser parser = new PosixParser();
			commandLine = parser.parse(commandPerformer.getCommandOptions(),
									   commandParamsLine);
		} catch (ParseException e) {
			return COMMAND_PARAM_INCORRECT_MESSAGE;
		}
		
		// ********************** Log **********************
		IgxLog.messageLog.info(this, "[console command]: '{}'",
				commandLineStr);
		// ********************** Log **********************
		
		// 執行指令
		String performResultMessage =
						commandPerformer.performCommand(commandLine);
		return performResultMessage;
	}
	
	public String getCommandHelpDescription() {
		StringBuffer commandHelpDescriptionStringBuf = new StringBuffer();
		
		Set<String> keyStrSet = this.commandPerformerMap.keySet();
		for (String keyStr : keyStrSet) {
			CommandPerformer commandPerformer = this.commandPerformerMap.get(keyStr);
			
			commandHelpDescriptionStringBuf.append("   [" + commandPerformer.getCommandName() + "] :  ");
			commandHelpDescriptionStringBuf.append(commandPerformer.getCommandDescription() + "\r\n");
		}
		
		return commandHelpDescriptionStringBuf.toString();
	}
	
	/**
	 * 根據給定的指令前置字元,找出符合的指令字串. 若找不到符合的指令,或找到二個以上的符合
	 * 字串將都會回傳null.
	 * @param cmdPrefix
	 * @return
	 */
	public String getMatchedCommandByGivenPrefix(String cmdPrefix) {
		Set<String> commandStrSet = this.commandPerformerMap.keySet();
		
		String matchedCommand = null;
		for (String commandStr : commandStrSet) {
			if (commandStr.startsWith(cmdPrefix)) {
				if (null == matchedCommand) {
					matchedCommand = commandStr;
				}
				else {
					return null;
				}
			}
		}
		
		return matchedCommand;
	}
	
	public void addCommandPerformer(CommandPerformer commandPerformer) {
		this.commandPerformerMap.put(commandPerformer.getCommandName(),
									 commandPerformer);
	}
	
	/**
	 * 取得所有的 CommandPerformer
	 * @return
	 */
	public List<CommandPerformer> getCommandPerformerList() {
		return
			new LinkedList<CommandPerformer>(this.commandPerformerMap.values());
	}
	
	// --- getter and setter ---
	
	public void setCommandPerformer(CommandPerformer ... commandPerformers ) {
		for (CommandPerformer commandPerformer : commandPerformers) {
			addCommandPerformer(commandPerformer);
		}
		
	}
}
